package com.xframe.xdal.core.util.redis.command;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xframe.xdal.core.model.IModel;
import com.xframe.xdal.core.util.StringUtil;
import com.xframe.xdal.core.util.redis.pool.IRedisPool;
import redis.clients.jedis.commands.JedisCommands;

import java.util.*;

public class HashCommand {

    private IRedisPool pool = null;

    public HashCommand(IRedisPool pool){
        this.pool = pool;
    }


    /**
     * 以秒为单位，返回给定 key 的剩余生存时间(TTL, time to live)。
     *
     * @param key   key
     *
     * @return 当 key 不存在时，返回 -2 。 当 key 存在但没有设置剩余生存时间时，返回 -1 。否则，以秒为单位，返回 key 的剩余生存时间。
     */
    public int hmset(String key, Map<String, String> data) {
        if (StringUtil.isValueNull(key,data)) {
            return 0;
        }
        JedisCommands client = pool.getClient();
        try {
            if(client.hmset(key,data).equalsIgnoreCase("ok")){
                return 1;
            } else {
                return 0;
            }
        } finally {
            pool.close(client);
        }
    }

    public int hmset(String key, String data) {
        if (StringUtil.isValueNull(key,data)) {
            return 0;
        }
        HashMap<String,String> map = new HashMap<>();
        map.put(data, data);
        return hmset(key,map);
    }

    /**
     * 返回哈希表 key 中所有域的值
     *
     * @param key   key
     *
     * @return 一个包含哈希表中所有值的表。
     * 当 key 不存在时，返回一个空表
     */
    public List<String> hvals(String key) {
        if (StringUtil.isValueNull(key)) {
            return null;
        }
        JedisCommands client = pool.getClient();
        try {
            return client.hvals(key);
        } finally {
            pool.close(client);
        }
    }

    /**
     * 删除哈希表 key 中的一个或多个指定域，不存在的域将被忽略
     *
     * @param key   key
     * @param fields   字段ID
     *
     * @return 被成功移除的域的数量，不包括被忽略的域。
     */
    public Long hdel(String key,String... fields) {
        if (StringUtil.isValueNull(key,fields)) {
            return 0L;
        }
        JedisCommands client = pool.getClient();
        try {
            return client.hdel(key,fields);
        } finally {
            pool.close(client);
        }
    }

    /**
     * 查看哈希表 key 中，给定域 field 是否存在。
     *
     * @param key   key
     * @param field   字段ID
     *
     * @return 如果哈希表含有给定域，返回 1 。 如果哈希表不含有给定域，或 key 不存在，返回 0 。
     */
    public Boolean hexists(String key,String field) {
        if (StringUtil.isValueNull(key,field)) {
            return false;
        }
        JedisCommands client = pool.getClient();
        try {
            return client.hexists(key,field);
        } finally {
            pool.close(client);
        }
    }


    public Boolean exists(String key) {
        if (StringUtil.isValueNull(key)) {
            return false;
        }
        JedisCommands client = pool.getClient();
        try {
            return client.exists(key);
        } finally {
            pool.close(client);
        }
    }


    /**
     * 返回哈希表 key 中给定域 field 的值。
     *
     * @param key   key
     * @param field   字段ID
     *
     * @return 给定域的值。
     * 当给定域不存在或是给定 key 不存在时，返回 nil 。
     */
    public String hget(String key,String field) {
        if (StringUtil.isValueNull(key,field)) {
            return null;
        }
        JedisCommands client = pool.getClient();
        try {
            return client.hget(key,field);
        } finally {
            pool.close(client);
        }
    }

    /**
     * 返回哈希表 key 中，所有的域和值。
     *
     * @param key   key
     *
     * @return 给定域的值。
     * 以列表形式返回哈希表的域和域的值。
     * 若 key 不存在，返回空列表。
     */
    public Map<String, String> hgetAll(String key) {
        if (StringUtil.isValueNull(key)) {
            return null;
        }
        JedisCommands client = pool.getClient();
        try {
            return client.hgetAll(key);
        } finally {
            pool.close(client);
        }
    }


    /**
     * 返回哈希表 key 中域的数量。
     *
     * @param key   key
     *
     * @return 哈希表中域的数量。
     * 当 key 不存在时，返回 0 。
     */
    public Long hlen(String key) {
        if (StringUtil.isValueNull(key)) {
            return 0L;
        }
        JedisCommands client = pool.getClient();
        try {
            return client.hlen(key);
        } finally {
            pool.close(client);
        }
    }


    /**
     * 返回哈希表 key 中，一个或多个给定域的值。
     *
     * 如果给定的域不存在于哈希表，那么返回一个 nil 值。
     *
     * 因为不存在的 key 被当作一个空哈希表来处理，所以对一个不存在的 key 进行 HMGET 操作将返回一个只带有 nil 值的表。
     *
     * @param key   key
     * @param fields   字段列表
     *
     * @return 一个包含多个给定域的关联值的表，表值的排列顺序和给定域参数的请求顺序一样。
     */
    public List<String> hmget(String key,String...fields) {
        if (StringUtil.isValueNull(key,fields)) {
            return null;
        }
        JedisCommands client = pool.getClient();
        try {
            return client.hmget(key,fields);
        } finally {
            pool.close(client);
        }
    }





    public Set<String> hkeys(String key) {
        if (StringUtil.isValueNull(key)) {
            return null;
        }
        JedisCommands client = pool.getClient();
        try {
            return  client.hkeys(key);
        } finally {
            pool.close(client);
        }
    }




    /**
     * 将哈希表 key 中的域 field 的值设为 value 。
     * 如果 key 不存在，一个新的哈希表被创建并进行 HSET 操作。
     * 如果域 field 已经存在于哈希表中，旧值将被覆盖。
     *
     * @param key   key
     * @param field  字段列表
     * @param value  字段值
     *
     * @return 如果 field 是哈希表中的一个新建域，并且值设置成功，返回 1，如果哈希表中域 field 已经存在且旧值已被新值覆盖，返回 0 。
     */
    public Long hset(String key,String field,String value) {
        if (StringUtil.isValueNull(key,field,value)) {
            return -1L;
        }
        JedisCommands client = pool.getClient();
        try {
            return client.hset(key,field,value);
        } finally {
            pool.close(client);
        }
    }

    /**
     * 将哈希表 key 中的域 field 的值设为 value 。
     * 如果 key 不存在，一个新的哈希表被创建并进行 HSET 操作。
     * 如果域 field 已经存在于哈希表中，旧值将被覆盖。
     *
     * @param key   key
     * @param keyValParam  名值对字典
     *
     * @return 如果 field 是哈希表中的一个新建域，并且值设置成功，返回 1，如果哈希表中域 field 已经存在且旧值已被新值覆盖，返回 0 。
     */
    public Long hset(String key,Map<String, String> keyValParam) {
        if (StringUtil.isValueNull(key,keyValParam)) {
            return -1L;
        }
        JedisCommands client = pool.getClient();
        try {
            return client.hset(key,keyValParam);
        } finally {
            pool.close(client);
        }
    }


    /**
     * 将哈希表 key 中的域 field 的值设置为 value ，当且仅当域 field 不存在
     * 若域 field 已经存在，该操作无效。如果 key 不存在，一个新哈希表被创建并执行 HSETNX 命令。
     *
     * @param key   key
     * @param field 字段键
     * @param value 字段值
     *
     * @return 设置成功，返回 1,如果给定域已经存在且没有操作被执行，返回 0
     */
    public Long hsetnx(String key,String field,String value) {
        if (StringUtil.isValueNull(key,field,value)) {
            return -1L;
        }
        JedisCommands client = pool.getClient();
        try {
            return client.hsetnx(key,field,value);
        } finally {
            pool.close(client);
        }
    }

    /**
     * hmset命令的封装 将一个对象集合用JSON的方式写入到一个哈希表中
     *
     *
     * @param key   key
     * @param list 写入的对象列表
     *
     * @return 如果命令执行成功，返回 OK 。
     */
    public <T extends IModel> int hmsetCollection(String key, Collection<T> list){
        if (StringUtil.isValueNull(key,list)) {
            return 0;
        }
        Map<String,String> data = new HashMap<>();
        for(IModel model : list){
            String mapKey = model.getObjectId().toString();
            String json = JSON.toJSONString(model);
            data.put(mapKey,json);
        }
        return hmset(key,data);
    }


    /**
     * hvals命令的封装 将一个列表的对象JSON字符串取出并反序列化成对象
     *
     *
     * @param key   key
     * @param dataType 返回对象类型
     *
     * @return 对象列表
     */
    public <T extends IModel> List<T> hvalsCollection(String key,Class dataType) {
        if (StringUtil.isValueNull(key,dataType)) {
            return null;
        }
        JedisCommands client = pool.getClient();
        try {
            List<T> list = new ArrayList<>();
            List<String> jsons = client.hvals(key);
            for (String json : jsons){
                JSONObject jsonObject = JSONObject.parseObject(json);
                T model = (T) JSON.toJavaObject(jsonObject, dataType);
                list.add(model);
            }
            return list;
        } finally {
            pool.close(client);
        }
    }
}
